import os
import time
import platform
from datetime import datetime
import ctypes
import glob


def get_memory_size():
    """跨平台获取内存大小（以GB为单位）"""
    system = platform.system()
    if system == "Linux":
        try:
            with open("/proc/meminfo", "r") as f:
                for line in f:
                    if "MemTotal" in line:
                        mem_kb = int(line.split(":")[1].strip().split()[0])
                        return round(mem_kb / 1024 / 1024, 2)
            return "Unknown Memory"
        except Exception:
            return "Unknown Memory"
    elif system == "Windows":
        try:
            result = os.popen("wmic computersystem get TotalPhysicalMemory").read().strip().split("\n")
            if len(result) > 1:
                mem_bytes = int(result[1].strip())
                return round(mem_bytes / (1024 ** 3), 2)
        except Exception:
            pass

        try:
            class MEMORYSTATUS(ctypes.Structure):
                _fields_ = [
                    ("dwLength", ctypes.c_ulong),
                    ("dwMemoryLoad", ctypes.c_ulong),
                    ("ullTotalPhys", ctypes.c_ulonglong),
                    ("ullAvailPhys", ctypes.c_ulonglong),
                    ("ullTotalPageFile", ctypes.c_ulonglong),
                    ("ullAvailPageFile", ctypes.c_ulonglong),
                    ("ullTotalVirtual", ctypes.c_ulonglong),
                    ("ullAvailVirtual", ctypes.c_ulonglong),
                    ("ullAvailExtendedVirtual", ctypes.c_ulonglong),
                ]

            memory_status = MEMORYSTATUS()
            memory_status.dwLength = ctypes.sizeof(MEMORYSTATUS)
            ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(memory_status))
            total_memory_gb = round(memory_status.ullTotalPhys / (1024 ** 3), 2)
            return total_memory_gb
        except Exception:
            return "Unknown Memory"
    else:
        return "Unsupported OS"


def high_cpu_load_test(duration=30):
    """高算力消耗测试：计算圆周率π的值，并显示进度"""
    print("1、开始算力测试（计算圆周率π的值）...")
    start_time = time.time()

    def calculate_pi(n_terms):
        numerator = 4.0
        denominator = 1.0
        operation = 1.0
        pi = 0.0
        for i in range(n_terms):
            pi += operation * (numerator / denominator)
            denominator += 2.0
            operation *= -1.0

            # 显示进度
            progress = (i + 1) / n_terms * 100
            elapsed = time.time() - start_time
            print(f"进度: {progress:.2f}%, 当前π值: {pi}, 已用时: {elapsed:.2f}秒", end="\r")

        return pi

    n_terms = 3 * 10 ** 7  # 计算项数
    print(f"准备重复计算 {n_terms} 次...")
    pi_value = calculate_pi(n_terms)

    end_time = time.time()
    elapsed_time = end_time - start_time
    print(f"\n计算完成！π值: {pi_value}")
    return elapsed_time


def cleanup_directory(directory):
    """清理指定目录下的所有文件"""
    files = glob.glob(os.path.join(directory, "*"))
    for file_path in files:
        try:
            os.remove(file_path)
        except Exception as e:
            print(f"无法删除文件 {file_path}: {e}")


def file_io_test(directory, num_large_files=10, large_file_size_gb=1, num_small_files=10000, small_file_size_kb=1):
    """文件I/O测试：大文件和小文件的创建与读取"""
    print("2、开始文件文件读写速度测试...")
    os.makedirs(directory, exist_ok=True)

    # 清理目录（不计入时间）
    cleanup_directory(directory)

    # 测试大文件
    print(f"2.1、开始大文件测试...(准备创建{large_file_size_gb}G的文本文件{num_large_files}个，并完成写入和读取)")
    large_files_total_time = 0
    chunk_size = 1024 * 1024 * 64  # 每次写入 64MB 的数据块
    for i in range(num_large_files):
        print(f"正在处理大文件 {i + 1}/{num_large_files}...")
        file_start_time = time.time()
        # 创建大文件
        filename = os.path.join(directory, f"large_file_{i}.dat")
        with open(filename, "wb") as f:
            bytes_to_write = large_file_size_gb * 1024 * 1024 * 1024  # 计算总字节数
            while bytes_to_write > 0:
                write_size = min(chunk_size, bytes_to_write)  # 确保不会超出剩余字节数
                f.write(b"1" * write_size)
                bytes_to_write -= write_size

        # 读取大文件
        with open(filename, "rb") as f:
            _ = f.read()

        file_end_time = time.time()
        file_time = file_end_time - file_start_time
        large_files_total_time += file_time
        print(f"大文件 {i + 1} 耗时: {file_time:.2f}秒")

    # 测试小文件
    print(f"2.2、开始小文件测试...准备创建并读写{small_file_size_kb}K的文件{num_small_files}个")
    small_files_total_time = 0
    for i in range(num_small_files):
        if i % 1000 == 0:
            print(f"正在处理小文件 {i + 1}/{num_small_files}...")

        file_start_time = time.time()

        # 创建小文件
        filename = os.path.join(directory, f"small_file_{i}.txt")
        with open(filename, "wb") as f:
            data = b"1" * (1024 * small_file_size_kb)  # 指定大小的小文件
            f.write(data)

        # 读取小文件
        with open(filename, "rb") as f:
            _ = f.read()

        file_end_time = time.time()
        file_time = file_end_time - file_start_time
        small_files_total_time += file_time

    # 显示目录中的文件
    print("\n当前目录中的文件列表如下：")
    files = os.listdir(directory)
    for idx, file_name in enumerate(files, start=1):
        print(f"{idx}. {file_name}")

    # 删除文件速度测试
    print("2.3、开始删除文件速度测试...")
    delete_start_time = time.time()
    cleanup_directory(directory)
    delete_end_time = time.time()
    delete_time = delete_end_time - delete_start_time
    print(f"删除文件速度测试完成，耗时: {delete_time:.2f}秒")

    print("文件I/O测试完成！")
    return large_files_total_time, small_files_total_time, delete_time

def generate_report(memory_size, cpu_test_time, large_files_time, small_files_time, delete_time):
    """生成测试报告，并显示报告内容"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    report_filename = f"测试报告_{timestamp}.txt"
    with open(report_filename, "w") as f:
        f.write("性能测试报告\n")
        f.write("=" * 30 + "\n")
        f.write(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        f.write(f"操作系统: {platform.system()} {platform.release()}\n")
        f.write(f"内存大小: {memory_size} GB\n")
        f.write(f"高算力消耗测试耗时: {cpu_test_time:.2f}秒\n")
        f.write(f"大文件I/O测试耗时: {large_files_time:.2f}秒\n")
        f.write(f"小文件I/O测试耗时: {small_files_time:.2f}秒\n")
        f.write(f"删除文件速度测试耗时: {delete_time:.2f}秒\n")
        f.write("\n测试完成！\n")

    # 打印报告内容到控制台
    print("\n测试报告内容如下：")
    print("=" * 30)
    with open(report_filename, "r") as f:
        print(f.read())
    print("=" * 30)

    print(f"测试报告已生成: {report_filename}")


if __name__ == "__main__":
    # 获取系统信息
    memory_size = get_memory_size()
    print(f"内存大小: {memory_size} GB")

    # 记录启动时间
    start_time = time.time()
    print(f"测试开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 40)

    # 高算力消耗测试
    cpu_test_time = high_cpu_load_test()

    # 文件I/O测试
    test_directory = "io_test"
    large_files_time, small_files_time, delete_time = file_io_test(test_directory)

    # 总耗时
    total_time = time.time() - start_time
    print(f"总耗时: {total_time:.2f}秒")

    # 生成测试报告
    generate_report(memory_size, cpu_test_time, large_files_time, small_files_time, delete_time)